import axios, { AxiosError } from 'axios';
import type { InternalAxiosRequestConfig, AxiosResponse , AxiosInstance, AxiosRequestConfig} from 'axios';
import { ElMessage } from 'element-plus'
import { removeToken, removeMenuList } from './auth';
// 是否显示重新登录
export let isRelogin = { show: false };

// 创建一个 axios 实例
const instance = axios.create({
    baseURL: import.meta.env.VITE_APP_BASE_API, // 你的 API 基础 URL
    timeout: 10000, // 请求超时时间
    headers: {
        'Content-Type': 'application/json',
    },
});

// 流下载实例
const streamDownload = axios.create({
    baseURL: import.meta.env.VITE_APP_BASE_API, // 你的 API 基础 URL
    timeout: 10000, // 请求超时时间
    headers: {
        'Content-Type': 'application/json',
    },
    responseType: 'arraybuffer',
});

// 文件上传实例
const fileUpload = axios.create({
    baseURL: import.meta.env.VITE_APP_BASE_API, // 你的 API 基础 URL
    timeout: 120000, // 请求超时时间
    headers: {
        'Content-Type': 'multipart/form-data',
    },
});

// 流式读取
const streamReader = axios.create({
    baseURL: import.meta.env.VITE_APP_BASE_API, // 你的 API 基础 URL
    timeout: 120000, // 请求超时时间
    headers: {
        'Content-Type': 'application/json',
    },
    responseType: 'stream',
});

// 用于存储最近300ms内的请求
const requestCache = new Map<string, number>();

// 定义一个函数来添加请求拦截器
function addRequestInterceptor(axiosInstance: AxiosInstance): void {
    axiosInstance.interceptors.request.use(
        (config: InternalAxiosRequestConfig) => {
            // 在发送请求之前做些什么，例如添加 token
            const token = localStorage.getItem('Z-Token');
            if (token) {
                config.headers['Z-Token'] = token;
            }
            // 防止重复请求
            let cacheKey;
            if (config.data) {
                cacheKey=  `${config.method}-${config.url} - ${JSON.stringify(config.data)}`;
            } else {
                cacheKey = `${config.method}-${config.url}`;
            }
            const currentTime = Date.now();
            const lastRequestTime = requestCache.get(cacheKey);
            if (lastRequestTime && currentTime - lastRequestTime < 300) {
                // ElMessage.warning('重复请求，请稍后再试');
                return Promise.reject(new Error('重复请求，请稍后再试'));
            }
            requestCache.set(cacheKey, currentTime);
            return config;
        },
        (error: any) => {
            // 对请求错误做些什么
            return Promise.reject(error);
        }
    );
}

// 添加请求拦截器到每个实例
addRequestInterceptor(instance);
addRequestInterceptor(streamDownload);
addRequestInterceptor(fileUpload);

// 请求拦截器
// instance.interceptors.request.use(
//     (config: InternalAxiosRequestConfig) => {
//         // 在发送请求之前做些什么，例如添加 token
//         const token = localStorage.getItem('Z-Token');
//         if (token) {
//             // config.headers['Authorization'] = `Bearer ${token}`;
//             config.headers['Z-Token'] = token;
//         }
//         // 防止重复请求
//         const cacheKey = `${config.method}-${config.url}`;
//         const currentTime = Date.now();
//         const lastRequestTime = requestCache.get(cacheKey);
//         if (lastRequestTime && currentTime - lastRequestTime < 300) {
//             // ElMessage.warning('重复请求，请稍后再试');
//             return Promise.reject(new Error('重复请求，请稍后再试'));
//         }
//         requestCache.set(cacheKey, currentTime);
//         return config;
//     },
//     (error: any) => {
//         // 对请求错误做些什么
//         return Promise.reject(error);
//     }
// );

// 响应拦截器res
instance.interceptors.response.use((res: AxiosResponse) => {
    // 未设置状态码则默认成功状态
    const code = res.data.status || 200;
    // 获取错误信息
    // const msg = errorCode[code] || res.data.msg || errorCode['default']
    const msg = res.data.msg;
    // 二进制数据则直接返回
    // if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
    //   return res.data
    // }
    if (code === 401) {
        // if (!isRelogin.show) {
        //     isRelogin.show = true;
        //     MessageBox.confirm('登录状态已过期，您可以继续留在该页面，或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
        //       isRelogin.show = false;
        //       store.dispatch('LogOut').then(() => {
        //         location.href = '/index';
        //       })
        //     }).catch(() => {
        //       isRelogin.show = false;
        //     });
        // }
        removeToken();
        removeMenuList();
        ElMessage({ message: '登录已过期，请重新登录！', type: 'warning', showClose: true })
        setTimeout(() => {
            window.location.href = "/login";
        }, 1500);
        return Promise.reject('无效的会话，或者会话已过期，请重新登录。')
    } else if (code === 500) {
        ElMessage({ message: msg, type: 'error', showClose: true })
        return Promise.reject(new Error(msg))
    } else if (code === 601) {
        ElMessage({ message: msg, type: 'warning' })
        return Promise.reject('error')
    } else if (code !== 200) {
        ElMessage({ message: msg, type: 'error', showClose: true })
        return Promise.reject('error')
    } else {
        return res.data
    }
},
    error => {
        console.log('err' + error)
        let { message } = error;
        if (message == "Network Error") {
            message = "后端接口连接异常";
        } else if (message.includes("timeout")) {
            message = "系统接口请求超时";
        } else if (message.includes("Request failed with status code")) {
            message = "系统接口" + message.substr(message.length - 3) + "异常";
        }
        // Message({ message: message, type: 'error', duration: 5 * 1000 })
        ElMessage({ message: message, type: 'error', showClose: true })
        return Promise.reject(error)
    }
);

// 封装 GET 请求
export const get = <T>(url: string, params?: any): Promise<T> => {
    return instance.get(url, { params });
};

// 封装 POST 请求
export const post = <T>(url: string, data?: any): Promise<T> => {
    return instance.post(url, data);
};

// 封装 PUT 请求
export const put = <T>(url: string, data?: any): Promise<T> => {
    return instance.put(url, data);
};

// 封装 DELETE 请求
export const del = <T>(url: string): Promise<T> => {
    return instance.delete(url);
};

// 封装 get 流下载 请求
export const streamGet = <T>(url: string): Promise<T> => {
    return streamDownload.get(url);
};

// 封装 post 流下载 请求
export const streamPost = <T>(url: string): Promise<T> => {
    return streamDownload.post(url);
};

// 封装 post 流式读取 请求
export const streamReaderPost = <T>(url: string, data?: any): Promise<T> => {
    return streamReader.post(url, data);
};

interface UploadProgressCallback {
    (percentCompleted: number): void;
}

// 封装 post 文件上传 请求
export const fileUploadPost = async <T>(
    url: string,
    data: any,
    onUploadProgress: UploadProgressCallback,
    options?: { signal?: AbortSignal }
): Promise<T> => {
    try {
        const response = await fileUpload.post(url, data, {
            ...options,
            onUploadProgress: (progressEvent) => {
                if (progressEvent.total) {
                    const percentCompleted = Math.round(
                        (progressEvent.loaded * 100) / progressEvent.total
                    );
                    onUploadProgress(percentCompleted);
                }
            },
        });
        return response.data;
    } catch (error) {
        const axiosError = error as AxiosError;
        if (axiosError.isAxiosError && axiosError.response) {
            // throw new Error(axiosError.response.data || 'Failed to upload file');
            throw new Error('Failed to upload file');
        } else if (axiosError.name === 'AbortError') {
            throw new Error('Upload canceled by user');
        } else {
            throw new Error('Failed to upload file');
        }
    }
};

// 默认导出 axios 实例
export default instance;
